package eval

import (
	"showen7/inter"
	"showen7/num"
)

func Add(args []inter.Object, env *inter.Environment) inter.Object {
	// Handle case with no arguments - return 0
	if len(args) == 0 {
		return &inter.NumberObject{Value: num.Integer(0)}
	}
	var result num.Number
	result = num.Integer(0)
	for _, arg := range args {
		if arg.Type() != inter.NUMBER_OBJ {
			return &Error{Message: "addition expects integer, rational or real numbers"}
		}
		intArg := arg.(*inter.NumberObject)
		result = result.ADD(intArg.Value)
	}

	return &inter.NumberObject{Value: result}
}

func Subtract(args []inter.Object, env *inter.Environment) inter.Object {
	// Handle case with no arguments - return 0
	if len(args) == 0 {
		return &inter.NumberObject{Value: num.Integer(0)}
	}
	
	// Handle case with one argument - return its negation
	if len(args) == 1 {
		if args[0].Type() != inter.NUMBER_OBJ {
			return &Error{Message: "subtraction expects integer, rational or real numbers"}
		}
		numArg := args[0].(*inter.NumberObject)
		return &inter.NumberObject{Value: numArg.Value.NEG()}
	}
	
	// Handle case with multiple arguments
	if args[0].Type() != inter.NUMBER_OBJ {
		return &Error{Message: "subtraction expects integer, rational or real numbers"}
	}
	result := args[0].(*inter.NumberObject).Value
	
	for _, arg := range args[1:] {
		if arg.Type() != inter.NUMBER_OBJ {
			return &Error{Message: "subtraction expects integer, rational or real numbers"}
		}
		intArg := arg.(*inter.NumberObject)
		result = result.SUB(intArg.Value)
	}

	return &inter.NumberObject{Value: result}
}

func Multiply(args []inter.Object, env *inter.Environment) inter.Object {
	// Handle case with no arguments - return 1
	if len(args) == 0 {
		return &inter.NumberObject{Value: num.Integer(1)}
	}
	
	var result num.Number
	result = num.Integer(1)
	for _, arg := range args {
		if arg.Type() != inter.NUMBER_OBJ {
			return &Error{Message: "multiplication expects integer, rational or real numbers"}
		}
		intArg := arg.(*inter.NumberObject)
		result = result.MUL(intArg.Value)
	}

	return &inter.NumberObject{Value: result}
}

func Divide(args []inter.Object, env *inter.Environment) inter.Object {
	// Handle case with no arguments - return 1
	if len(args) == 0 {
		return &inter.NumberObject{Value: num.Integer(1)}
	}
	
	// Handle case with one argument - return 1 divided by that number
	if len(args) == 1 {
		if args[0].Type() != inter.NUMBER_OBJ {
			return &Error{Message: "division expects integer, rational or real numbers"}
		}
		one := &inter.NumberObject{Value: num.Integer(1)}
		numArg := args[0].(*inter.NumberObject)
		result := one.Value.DIV(numArg.Value)
		return &inter.NumberObject{Value: result}
	}
	
	// Handle case with multiple arguments
	if args[0].Type() != inter.NUMBER_OBJ {
		return &Error{Message: "division expects integer, rational or real numbers"}
	}
	result := args[0].(*inter.NumberObject).Value
	
	for _, arg := range args[1:] {
		if arg.Type() != inter.NUMBER_OBJ {
			return &Error{Message: "division expects integer, rational or real numbers"}
		}
		intArg := arg.(*inter.NumberObject)
		result = result.DIV(intArg.Value)
	}

	return &inter.NumberObject{Value: result}
}